package com.easpeed.comon.utils

import android.content.Context
import android.graphics.Point
import android.os.Bundle
import android.util.Log;
import com.bigyu.utils.Logger
import android.view.View
import android.view.animation.LinearInterpolator
import com.baidu.mapapi.animation.Animation
import com.baidu.mapapi.animation.Transformation
import com.baidu.mapapi.map.*
import com.baidu.mapapi.model.LatLng
import com.baidu.mapapi.model.LatLngBounds
import com.easpeed.comon.bean.LatLngCommon
import java.lang.RuntimeException


/**
 * 百度地图的工具类
 */
class YFMapUtilsBaidu(var mContext: Context, var baiduMap: BaiduMap? = null) {

    private var iconMap = HashMap<String, BitmapDescriptor?>()

    init {

        if (baiduMap != null) {
            setMap(baiduMap)
        }
    }

    public fun setMap(map: BaiduMap?) {
        baiduMap = map
        initListener()
    }

    fun initListener() {
        baiduMap?.setOnMapLoadedCallback {
            mapLoadedCallBack?.invoke()
        }
    }


    /**
     * 绘制marker
     * @param icon {@see getMapIcon()}
     */
    public fun drawMarker(
        latLng: LatLng?,
        icon: BitmapDescriptor?,
        markerCenterDefault: Boolean = false,
    ): Marker? {
        check()
        var offset = 0.5f
        if (markerCenterDefault) {
            offset = 1f
        }

        //构建MarkerOption，用于在地图上添加Marker
        val option: OverlayOptions = MarkerOptions()
            .position(latLng)
            .anchor(0.5f, offset)
            .zIndex(Int.MAX_VALUE)
            .clickable(true)
            .icon(icon)
        //在地图上添加Marker，并显示
//        MLogger.e("----", "绘制marker$latLng")
        return baiduMap?.addOverlay(option) as Marker
    }

    public fun drawTextureLine(list: List<LatLng>, icon: BitmapDescriptor?): Overlay? {
        check()
        if (list.size < 2) {
            return null
        }
        //添加纹理索引
        val indexList = ArrayList<Int>().apply {
            add(0)
        }
        //设置折线的属性
        val mOverlayOptions: PolylineOptions =
            PolylineOptions().width(16)
                .dottedLine(true)
                .points(list)
                .isThined(true)
                .clickable(false)
                .customTexture(icon)
                .zIndex(1)
                .textureIndex(indexList) //设置纹理列表
        return baiduMap?.addOverlay(mOverlayOptions)
    }


    /**
     * marker点击事件
     */
    public fun setOnMarkerClickListener(listener: BaiduMap.OnMarkerClickListener?) {
        check()
        baiduMap?.setOnMarkerClickListener(listener)
    }

    /**
     * 地图点击事件
     */
    public fun setOnMapClickListener(listener: BaiduMap.OnMapClickListener?) {
        check()
        baiduMap?.setOnMapClickListener(listener)
    }

    /**
     * 绘制圆形区域
     */
    public fun drawCircleOverlay(
        latLng: LatLngCommon?,
        radius: Int,
        colorFill: Int,
        colorStroke: Int,
    ): Overlay? {
        check()
        latLng?.let {
            //圆心位置
            val center = LatLng(it.lat, it.lng)
            //构造CircleOptions对象
            val mCircleOptions = CircleOptions().center(center)
                .radius(radius)
                .fillColor(colorFill) //填充颜色
                .stroke(Stroke(2, colorStroke)) //边框宽和边框颜色
            //在地图上显示圆
            val mCircle: Overlay? = baiduMap?.addOverlay(mCircleOptions)
            return mCircle
        }
        return null
    }

    /**
     * 绘制多边形形区域
     */
    public fun drawPolygonOverlay(
        latLng: List<LatLng>?,
        colorFill: Int,
        colorStroke: Int,
    ): Overlay? {
        check()
        latLng?.let {
            if (it.size <= 2) {
                return null
            }
            //构造CircleOptions对象
            val mCircleOptions = PolygonOptions()
                .points(latLng)
                .fillColor(colorFill) //填充颜色
                .stroke(Stroke(2, colorStroke)) //边框宽和边框颜色
            //在地图上显示圆
            val mCircle: Overlay? = baiduMap?.addOverlay(mCircleOptions)
            return mCircle
        }
        return null
    }

    /**
     * 设置交通图
     */
    public fun setTrafficEnabled(enable: Boolean) {
        check()
        baiduMap?.isTrafficEnabled = enable
    }

    /**
     * 设置地图类型
     */
    public fun setMapType(enable: Boolean) {
        check()
        if (!enable) {
            baiduMap?.mapType = BaiduMap.MAP_TYPE_NORMAL
        } else {
            baiduMap?.mapType = BaiduMap.MAP_TYPE_SATELLITE
        }
    }

    /**
     * 地图中心到坐标点
     */
    public fun moveCamera(latLng: LatLng?, duration: Int) {
        check()
        val status1 = MapStatusUpdateFactory.newLatLng(latLng)
        baiduMap?.animateMapStatus(status1, duration)
    }

    public fun zoomTo(z: Float, duration: Int) {
        check()
        baiduMap?.animateMapStatus(MapStatusUpdateFactory.zoomTo(z), duration)
    }

    public fun moveCameraZoomTo(latLng: LatLng?, z: Float, duration: Int) {
        check()
        baiduMap?.animateMapStatus(MapStatusUpdateFactory.newLatLngZoom(latLng, z), duration)
    }

    private var iconMapInt = HashMap<Int, BitmapDescriptor?>()

    /**
     * 获取marker的icon
     */
    public fun getMapIcon(res: Int): BitmapDescriptor? {
        var bitmapDescriptor = iconMapInt[res]
        if (bitmapDescriptor == null) {
            bitmapDescriptor = BitmapDescriptorFactory.fromResource(res).apply {
                iconMapInt[res] = this
            }
        }
        return bitmapDescriptor
    }

    /**
     * 获取marker的icon
     */
    public fun getMapIcon(view: View?): BitmapDescriptor? {
        var bitmapDescriptor = iconMap["$view"]
        if (bitmapDescriptor == null) {
            bitmapDescriptor = BitmapDescriptorFactory.fromView(view).apply {
                iconMap["$view"] = this
            }
        }
        return bitmapDescriptor
    }

    /**
     * 获取marker的icon
     */
    public fun getMapIcon(res: String): BitmapDescriptor? {
        var bitmapDescriptor = iconMap[res]
        if (bitmapDescriptor == null) {
            bitmapDescriptor = BitmapDescriptorFactory.fromAsset(res).apply {
                iconMap[res] = this
            }
        }
        return bitmapDescriptor
    }

    /**
     * 检查初始化属性
     */
    private fun check() {
        if (baiduMap == null) {
            throw RuntimeException("请设置YFMapUtilsBaidu.setMap()")
        }
    }


    /**
     * 多个点在地图中最佳显示
     */
    fun pointBastInScreen(
        points: List<LatLng>?,
    ) {
        check()
        if (points != null && baiduMap != null) {
            var builder = LatLngBounds.Builder()
            for (p in points) {
                builder = builder.include(p)
            }
            val latlngBounds = builder.build()
            val u = MapStatusUpdateFactory.newLatLngBounds(
                latlngBounds, 200, 200, 200, 200
            )
            baiduMap?.animateMapStatus(u, 100)
        }
    }


    companion object {

        public fun getZoom(distance: Int): Float {
            if (distance < 10) {
                return 20f
            } else if (distance < 50) {
                return 19f
            } else if (distance < 50) {
                return 18f
            } else if (distance < 100) {
                return 17f
            } else if (distance < 200) {
                return 16f
            } else if (distance < 500) {
                return 15f
            } else if (distance < 1000) {
                return 14f
            } else if (distance < 2000) {
                return 13f
            } else if (distance < 5000) {
                return 12f
            } else if (distance < 10000) {
                return 11f
            } else return 10f
        }
    }

    /**
     * @param latLng 坐标点
     * @return 判断点坐标是否在屏幕内
     */
    fun pointIsOnscreen(latLng: LatLng?): Boolean {
        if (latLng == null) {
            return false
        }
        if (baiduMap == null) {
            return false
        }
        try {
            val point = baiduMap?.projection?.toScreenLocation(latLng)!!
            val pt = baiduMap?.mapStatus?.targetScreen!!
            return point.x >= 0 && point.y >= 0 && point.x <= pt.x * 2 && point.y <= pt.y * 2
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return false
    }


//    ***********************************************************************************

    fun pointTest(latLng: LatLng?, point: Point, during: Int = 100): Boolean {
        if (latLng == null) {
            return false
        }
        if (baiduMap == null) {
            return false
        }
        try {
            val targetPoint = baiduMap?.projection?.toScreenLocation(latLng)!!
            val pt = baiduMap?.mapStatus?.targetScreen!!

            // 计算偏移量
            val dx = point.x - targetPoint.x
            val dy = point.y - targetPoint.y
//            Logger.d("MapTest", "Offset dx: $dx, dy: $dy   point:$point   targetPoint:$targetPoint  地图中心点:$pt ${BarUtils.getStatusBarHeight(mContext)}  ${ScreenUtils.getScreenHeight()}")
            // 移动地图，使目标经纬度移动到指定屏幕点位置
            baiduMap?.animateMapStatus(MapStatusUpdateFactory.scrollBy(-dx, -dy), during)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return true
    }

    /**
     * @param latLng 坐标点
     * @return 判断点坐标是否在屏幕内
     */
    fun pointIsOnscreen(latLng: LatLng?, centerPoint: Point): Boolean {
        if (latLng == null) {
            return false
        }
        if (baiduMap == null) {
            return false
        }
        try {
            val point = baiduMap?.projection?.toScreenLocation(latLng)!!
            val pt = centerPoint
            return point.x >= 0 && point.y >= 0 && point.x <= pt.x * 2 && point.y <= pt.y * 2
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return false
    }


    fun drawOrUpdateMarkerInfo(marker: Marker?, latLng: LatLng?, icon: BitmapDescriptor?, tag: String): Marker? {
        check()
        if (marker == null) {
            if (latLng == null) {
                return null
            }
            if (icon == null) {
                return null
            }
            //构建MarkerOption，用于在地图上添加Marker
            val option: OverlayOptions = MarkerOptions()
                .position(latLng)
                .anchor(0.5f, 1f)
                .yOffset(-120)
                .icon(icon)
            //在地图上添加Marker，并显示
            val newMarker = baiduMap?.addOverlay(option) as Marker
            newMarker.extraInfo = Bundle().apply {
                putString("tag", tag)
            }
            return newMarker
        } else {
            if (latLng != null) {
                marker.position = latLng
            }
            if (icon != null) {
                marker.icon = icon
            }
        }
        return marker
    }

    /**
     * @param animal 是否动画
     *
     * @param z -1表示没有缩放层级
     */
    @JvmOverloads
    fun moveCameraZoomTo(latLng: LatLng?, z: Float, animal: Boolean = true, callback: (() -> Unit)? = null) {
        check()
        latLng?.let {
            val newLatLngZoom = if (z == -1f) {
                MapStatusUpdateFactory.newLatLng(latLng)
            } else {
                MapStatusUpdateFactory.newLatLngZoom(latLng, z)
            }
            if (animal) {
                baiduMap?.animateMapStatus(newLatLngZoom, 200)
            } else {
                baiduMap?.setMapStatus(newLatLngZoom)
            }
        }
    }


    fun drawOrUpdateTextureLine(polyline: Polyline?, c: List<LatLng>, icon: BitmapDescriptor?): Polyline? {
        check()
        if (c.size < 2) {
            return null
        }
        if (polyline == null) {
            //添加纹理索引
            val indexList = ArrayList<Int>().apply {
                add(0)
            }
            //设置折线的属性
            val mOverlayOptions: PolylineOptions =
                PolylineOptions().width(16)
                    .dottedLine(true)
                    .points(c)
                    .isThined(true)
                    .customTexture(icon)
                    .lineJoinType(PolylineOptions.LineJoinType.LineJoinBevel)
                    .textureIndex(indexList) //设置纹理列表
            return baiduMap?.addOverlay(mOverlayOptions) as Polyline?
        } else {
            polyline.points = c
            return polyline
        }
    }

    /**
     * 多个点在地图中最佳显示
     */
    fun pointBastInScreen(points: MutableList<LatLng>?, left: Int = 200, top: Int = 200, right: Int = 200, bottom: Int = 200) {
        check()
        if (points != null && baiduMap != null) {
            var builder = LatLngBounds.Builder()
            for (p in points) {
                builder = builder.include(p)
            }
            val latlngBounds = builder.build()
            val u = MapStatusUpdateFactory.newLatLngBounds(
                latlngBounds, left, top, right, bottom
            )
            baiduMap?.animateMapStatus(u, 200)
        }
    }

    @JvmOverloads
    fun drawOrUpdate(
        marker: Marker?,
        latLng: LatLng?,
        icon: BitmapDescriptor?,
        isCenterMarker: Boolean = false,
        tag: String,
    ): Marker? {
        if (marker == null) {
            //构建MarkerOption，用于在地图上添加Marker
            val option: OverlayOptions = MarkerOptions()
                .position(latLng)
                .icon(icon)
            //在地图上添加Marker，并显示
            val newMarker = baiduMap?.addOverlay(option) as Marker
            var offset = 0.5f
            if (isCenterMarker) {
                offset = 1f
            }
            newMarker.setAnchor(0.5f, offset)
            newMarker.extraInfo = Bundle().apply {
                putString("tag", tag)
            }
            return newMarker
        } else {
            if (latLng != null) {
                marker.position = latLng
            }
            if (icon != null) {
                marker.icon = icon
            }
            var offset = 0.5f
            if (isCenterMarker) {
                offset = 1f
            }
            marker.setAnchor(0.5f, offset)
        }
        return marker
    }

    /**
     * 设置logo的偏移
     */
    fun setLogoPadding(left: Int, top: Int, right: Int, bottom: Int) {
        baiduMap?.setViewPadding(left, top, right, bottom)
    }

    private var mapLoadedCallBack: (() -> Unit)? = null
    fun setOnMapLoadedCallback(callback: (() -> Unit)?) {
        mapLoadedCallBack = callback
    }
}